#pragma once

#include <cstdio>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>

#define FIFO_PATHNAME "./fifo"

#define FILE_SRC_PATHNAME "./log.txt"
#define FILE_COPY_PATHNAME "./log.backup"

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

class NamedPipe
{
public:
    NamedPipe(const char *pathname) : _pathname(pathname)
    {
        int ret = mkfifo(_pathname.c_str(), 0666);
        if (ret < 0)
            ERR_EXIT("mkfifo");
        std::cout << "creat pipe success" << std::endl;
    }
    ~NamedPipe()
    {
        int ret = unlink(_pathname.c_str());
        if (ret < 0)
            ERR_EXIT("unlink");
        std::cout << "unlink pipe success" << std::endl;
    }

private:
    std::string _pathname;
};

class FileCopy
{
public:
    FileCopy(const char *pipepathname, const char *filepathname)
        : _pipepathname(pipepathname), _filepathname(filepathname)
    {
    }
    void OpenForRead()
    {
        // 假定文件默认存在
        _ffd = open(_filepathname.c_str(), O_RDONLY);
        if (_ffd < 0)
            ERR_EXIT("open");
    }
    void OpenForWrite()
    {
        _ffd = open(_filepathname.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
        if (_ffd < 0)
            ERR_EXIT("open");
    }
    void WritePipe()
    {
        _pfd = open(_pipepathname.c_str(), O_WRONLY);
        if (_ffd < 0)
            ERR_EXIT("open");
        char buff[1024];
        int n = 0;
        while ((n = read(_ffd, buff, sizeof(buff))) > 0) // 读文件
        {
            // 写管道
            write(_pfd, buff, n);
        }
    }
    void ReadPipe()
    {
        _pfd = open(_pipepathname.c_str(), O_RDONLY);
        if (_ffd < 0)
            ERR_EXIT("open");
        char buff[1024];
        int n = 0;
        while ((n = read(_pfd, buff, sizeof(buff))) > 0) // 读管道
        {
            // 写文件
            write(_ffd, buff, n);
        }
    }
    ~FileCopy()
    {
        int ret = close(_ffd);
        if (ret < 0)
            ERR_EXIT("close");
        ret = close(_pfd);
        if (ret < 0)
            ERR_EXIT("close");
        std::cout << "close file&pipe success" << std::endl;   
    }

private:
    std::string _pipepathname;
    std::string _filepathname;
    int _ffd = -1;
    int _pfd = -1;
};